Fix Android layout jump when navigating with IME open and NavBarIsVisible=false#34621
Fix Android layout jump when navigating with IME open and NavBarIsVisible=false#34621jpd21122012 wants to merge 3 commits intodotnet:mainfrom
Conversation
|
🚀 Dogfood this PR with:
curl -fsSL https://raw.githubusercontent.com/dotnet/maui/main/eng/scripts/get-maui-pr.sh | bash -s -- 34621Or
iex "& { $(irm https://raw.githubusercontent.com/dotnet/maui/main/eng/scripts/get-maui-pr.ps1) } 34621" |
There was a problem hiding this comment.
Pull request overview
Fixes an Android Shell navigation layout jump when transitioning while the soft keyboard (IME) is visible—especially when navigating to destinations with Shell.NavBarIsVisible=false.
Changes:
- Dismisses the soft keyboard before committing the fragment transaction in
ShellRenderer.SwitchFragment. - Adds a HostApp repro page for issue #34584 (keyboard open → navigate to NavBar hidden page).
- Adds an Android UI test intended to validate the destination content is not laid out under the status bar.
Reviewed changes
Copilot reviewed 3 out of 3 changed files in this pull request and generated 3 comments.
| File | Description |
|---|---|
| src/Controls/src/Core/Compatibility/Handlers/Shell/Android/ShellRenderer.cs | Attempts to hide IME before fragment replacement to stabilize insets/layout. |
| src/Controls/tests/TestCases.HostApp/Issues/Issue34584.cs | Adds a Shell-based repro page with an Entry + navigation to a NavBar-hidden destination. |
| src/Controls/tests/TestCases.Shared.Tests/Tests/Issues/Issue34584.cs | Adds an Android UI test to verify final element Y-position is below the status bar after navigation. |
src/Controls/src/Core/Compatibility/Handlers/Shell/Android/ShellRenderer.cs
Show resolved
Hide resolved
src/Controls/tests/TestCases.Shared.Tests/Tests/Issues/Issue34584.cs
Outdated
Show resolved
Hide resolved
Update the test to trigger navigation from Entry.Completed instead of a button tap, ensuring the soft keyboard (IME) remains visible at the moment navigation occurs. This makes the test deterministic and accurately reproduces the original issue scenario.
🧪 PR Test EvaluationOverall Verdict: The test exercises the correct code path and the fix is Android-only with a matching platform guard, but the assertion is weak and there are minor issues (unused HostApp element, redundant null check, missing edge cases).
📊 Expand Full EvaluationPR Test Evaluation ReportPR: #34621 — Fix Android layout jump when navigating with IME open and NavBarIsVisible=false Overall VerdictThe test correctly exercises the fix's code path, but the assertion ( 1. Fix Coverage — ✅The fix calls 2. Edge Cases & Gaps —
|
## Summary Enables the copilot-evaluate-tests gh-aw workflow to run on fork PRs by adding `forks: ["*"]` to the `pull_request` trigger and removing the fork guard from `Checkout-GhAwPr.ps1`. ## Changes 1. **copilot-evaluate-tests.md**: Added `forks: ["*"]` to opt out of gh-aw auto-injected fork activation guard. Scoped `Checkout-GhAwPr.ps1` step to `workflow_dispatch` only (redundant for other triggers since platform handles checkout). 2. **copilot-evaluate-tests.lock.yml**: Recompiled via `gh aw compile` — fork guard removed from activation `if:` conditions. 3. **Checkout-GhAwPr.ps1**: Removed the `isCrossRepository` fork guard. Updated header docs and restore comments to accurately describe behavior for all trigger×fork combinations (including corrected step ordering). 4. **gh-aw-workflows.instructions.md**: Updated all stale references to the removed fork guard. Documented `forks: ["*"]` opt-in, clarified residual risk model for fork PRs, and updated troubleshooting table. ## Security Model Fork PRs are safe because: - Agent runs in **sandboxed container** with all credentials scrubbed - Output limited to **1 comment** via `safe-outputs: add-comment: max: 1` - Agent **prompt comes from base branch** (`runtime-import`) — forks cannot alter instructions - Pre-flight check catches missing `SKILL.md` if fork isn't rebased on `main` - No workspace code is executed with `GITHUB_TOKEN` (checkout without execution) ## Testing - ✅ `workflow_dispatch` tested against fork PR #34621 - ✅ Lock.yml statically verified — fork guard removed from `if:` conditions - ⏳ `pull_request` trigger on fork PRs can only be verified post-merge (GitHub Actions reads lock.yml from default branch) --------- Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com> Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
🚦 Gate - Test Before and After Fix📊 Expand Full Gate —
|
| Test | Without Fix (expect FAIL) | With Fix (expect PASS) |
|---|---|---|
🖥️ Issue34584 Issue34584 |
❌ PASS — 1664s | ✅ PASS — 514s |
🔴 Without fix — 🖥️ Issue34584: PASS ❌ · 1664s
(truncated to last 15,000 chars)
ackageAsync(AndroidDevice device, PushAndInstallCommand command, CancellationToken token) [/home/vsts/work/1/s/src/Controls/tests/TestCases.HostApp/Controls.TestCases.HostApp.csproj::TargetFramework=net10.0-android]
/home/vsts/work/1/s/.dotnet/packs/Microsoft.Android.Sdk.Linux/36.1.2/tools/Xamarin.Android.Common.Debugging.targets(333,5): error ADB0010: at AndroidDeviceExtensions.PushAndInstallPackageAsync(AndroidDevice device, PushAndInstallCommand command, CancellationToken token) [/home/vsts/work/1/s/src/Controls/tests/TestCases.HostApp/Controls.TestCases.HostApp.csproj::TargetFramework=net10.0-android]
/home/vsts/work/1/s/.dotnet/packs/Microsoft.Android.Sdk.Linux/36.1.2/tools/Xamarin.Android.Common.Debugging.targets(333,5): error ADB0010: at Xamarin.Android.Tasks.FastDeploy.InstallPackage(Boolean installed) [/home/vsts/work/1/s/src/Controls/tests/TestCases.HostApp/Controls.TestCases.HostApp.csproj::TargetFramework=net10.0-android]
/home/vsts/work/1/s/.dotnet/packs/Microsoft.Android.Sdk.Linux/36.1.2/tools/Xamarin.Android.Common.Debugging.targets(333,5): error ADB0010: at Xamarin.Android.Tasks.FastDeploy.InstallPackage(Boolean installed) [/home/vsts/work/1/s/src/Controls/tests/TestCases.HostApp/Controls.TestCases.HostApp.csproj::TargetFramework=net10.0-android]
/home/vsts/work/1/s/.dotnet/packs/Microsoft.Android.Sdk.Linux/36.1.2/tools/Xamarin.Android.Common.Debugging.targets(333,5): error ADB0010: at Xamarin.Android.Tasks.FastDeploy.RunInstall() [/home/vsts/work/1/s/src/Controls/tests/TestCases.HostApp/Controls.TestCases.HostApp.csproj::TargetFramework=net10.0-android]
Build FAILED.
/home/vsts/work/1/s/.dotnet/packs/Microsoft.Android.Sdk.Linux/36.1.2/tools/Xamarin.Android.Common.Debugging.targets(333,5): error ADB0010: Mono.AndroidTools.InstallFailedException: Unexpected install output: cmd: Failure calling service package: Broken pipe (32) [/home/vsts/work/1/s/src/Controls/tests/TestCases.HostApp/Controls.TestCases.HostApp.csproj::TargetFramework=net10.0-android]
/home/vsts/work/1/s/.dotnet/packs/Microsoft.Android.Sdk.Linux/36.1.2/tools/Xamarin.Android.Common.Debugging.targets(333,5): error ADB0010: [/home/vsts/work/1/s/src/Controls/tests/TestCases.HostApp/Controls.TestCases.HostApp.csproj::TargetFramework=net10.0-android]
/home/vsts/work/1/s/.dotnet/packs/Microsoft.Android.Sdk.Linux/36.1.2/tools/Xamarin.Android.Common.Debugging.targets(333,5): error ADB0010: at Mono.AndroidTools.Internal.AdbOutputParsing.CheckInstallSuccess(String output, String packageName) [/home/vsts/work/1/s/src/Controls/tests/TestCases.HostApp/Controls.TestCases.HostApp.csproj::TargetFramework=net10.0-android]
/home/vsts/work/1/s/.dotnet/packs/Microsoft.Android.Sdk.Linux/36.1.2/tools/Xamarin.Android.Common.Debugging.targets(333,5): error ADB0010: at Mono.AndroidTools.AndroidDevice.<>c__DisplayClass105_0.<InstallPackage>b__0(Task`1 t) [/home/vsts/work/1/s/src/Controls/tests/TestCases.HostApp/Controls.TestCases.HostApp.csproj::TargetFramework=net10.0-android]
/home/vsts/work/1/s/.dotnet/packs/Microsoft.Android.Sdk.Linux/36.1.2/tools/Xamarin.Android.Common.Debugging.targets(333,5): error ADB0010: at System.Threading.ExecutionContext.RunInternal(ExecutionContext executionContext, ContextCallback callback, Object state) [/home/vsts/work/1/s/src/Controls/tests/TestCases.HostApp/Controls.TestCases.HostApp.csproj::TargetFramework=net10.0-android]
/home/vsts/work/1/s/.dotnet/packs/Microsoft.Android.Sdk.Linux/36.1.2/tools/Xamarin.Android.Common.Debugging.targets(333,5): error ADB0010: --- End of stack trace from previous location --- [/home/vsts/work/1/s/src/Controls/tests/TestCases.HostApp/Controls.TestCases.HostApp.csproj::TargetFramework=net10.0-android]
/home/vsts/work/1/s/.dotnet/packs/Microsoft.Android.Sdk.Linux/36.1.2/tools/Xamarin.Android.Common.Debugging.targets(333,5): error ADB0010: at System.Threading.ExecutionContext.RunInternal(ExecutionContext executionContext, ContextCallback callback, Object state) [/home/vsts/work/1/s/src/Controls/tests/TestCases.HostApp/Controls.TestCases.HostApp.csproj::TargetFramework=net10.0-android]
/home/vsts/work/1/s/.dotnet/packs/Microsoft.Android.Sdk.Linux/36.1.2/tools/Xamarin.Android.Common.Debugging.targets(333,5): error ADB0010: at System.Threading.Tasks.Task.ExecuteWithThreadLocal(Task& currentTaskSlot, Thread threadPoolThread) [/home/vsts/work/1/s/src/Controls/tests/TestCases.HostApp/Controls.TestCases.HostApp.csproj::TargetFramework=net10.0-android]
/home/vsts/work/1/s/.dotnet/packs/Microsoft.Android.Sdk.Linux/36.1.2/tools/Xamarin.Android.Common.Debugging.targets(333,5): error ADB0010: --- End of stack trace from previous location --- [/home/vsts/work/1/s/src/Controls/tests/TestCases.HostApp/Controls.TestCases.HostApp.csproj::TargetFramework=net10.0-android]
/home/vsts/work/1/s/.dotnet/packs/Microsoft.Android.Sdk.Linux/36.1.2/tools/Xamarin.Android.Common.Debugging.targets(333,5): error ADB0010: at AndroidDeviceExtensions.PushAndInstallPackageAsync(AndroidDevice device, PushAndInstallCommand command, CancellationToken token) [/home/vsts/work/1/s/src/Controls/tests/TestCases.HostApp/Controls.TestCases.HostApp.csproj::TargetFramework=net10.0-android]
/home/vsts/work/1/s/.dotnet/packs/Microsoft.Android.Sdk.Linux/36.1.2/tools/Xamarin.Android.Common.Debugging.targets(333,5): error ADB0010: at AndroidDeviceExtensions.PushAndInstallPackageAsync(AndroidDevice device, PushAndInstallCommand command, CancellationToken token) [/home/vsts/work/1/s/src/Controls/tests/TestCases.HostApp/Controls.TestCases.HostApp.csproj::TargetFramework=net10.0-android]
/home/vsts/work/1/s/.dotnet/packs/Microsoft.Android.Sdk.Linux/36.1.2/tools/Xamarin.Android.Common.Debugging.targets(333,5): error ADB0010: at Xamarin.Android.Tasks.FastDeploy.InstallPackage(Boolean installed) [/home/vsts/work/1/s/src/Controls/tests/TestCases.HostApp/Controls.TestCases.HostApp.csproj::TargetFramework=net10.0-android]
/home/vsts/work/1/s/.dotnet/packs/Microsoft.Android.Sdk.Linux/36.1.2/tools/Xamarin.Android.Common.Debugging.targets(333,5): error ADB0010: at Xamarin.Android.Tasks.FastDeploy.InstallPackage(Boolean installed) [/home/vsts/work/1/s/src/Controls/tests/TestCases.HostApp/Controls.TestCases.HostApp.csproj::TargetFramework=net10.0-android]
/home/vsts/work/1/s/.dotnet/packs/Microsoft.Android.Sdk.Linux/36.1.2/tools/Xamarin.Android.Common.Debugging.targets(333,5): error ADB0010: at Xamarin.Android.Tasks.FastDeploy.RunInstall() [/home/vsts/work/1/s/src/Controls/tests/TestCases.HostApp/Controls.TestCases.HostApp.csproj::TargetFramework=net10.0-android]
0 Warning(s)
1 Error(s)
Time Elapsed 00:16:18.38
* daemon not running; starting now at tcp:5037
* daemon started successfully
Determining projects to restore...
All projects are up-to-date for restore.
##vso[build.updatebuildnumber]10.0.60-ci+azdo.13756416
Graphics -> /home/vsts/work/1/s/artifacts/bin/Graphics/Debug/net10.0-android36.0/Microsoft.Maui.Graphics.dll
##vso[build.updatebuildnumber]10.0.60-ci+azdo.13756416
Essentials -> /home/vsts/work/1/s/artifacts/bin/Essentials/Debug/net10.0-android36.0/Microsoft.Maui.Essentials.dll
##vso[build.updatebuildnumber]10.0.60-ci+azdo.13756416
Core -> /home/vsts/work/1/s/artifacts/bin/Core/Debug/net10.0-android36.0/Microsoft.Maui.dll
Controls.BindingSourceGen -> /home/vsts/work/1/s/artifacts/bin/Controls.BindingSourceGen/Debug/netstandard2.0/Microsoft.Maui.Controls.BindingSourceGen.dll
##vso[build.updatebuildnumber]10.0.60-ci+azdo.13756416
Maps -> /home/vsts/work/1/s/artifacts/bin/Maps/Debug/net10.0-android36.0/Microsoft.Maui.Maps.dll
##vso[build.updatebuildnumber]10.0.60-ci+azdo.13756416
Controls.Core -> /home/vsts/work/1/s/artifacts/bin/Controls.Core/Debug/net10.0-android36.0/Microsoft.Maui.Controls.dll
##vso[build.updatebuildnumber]10.0.60-ci+azdo.13756416
##vso[build.updatebuildnumber]10.0.60-ci+azdo.13756416
##vso[build.updatebuildnumber]10.0.60-ci+azdo.13756416
Controls.Xaml -> /home/vsts/work/1/s/artifacts/bin/Controls.Xaml/Debug/net10.0-android36.0/Microsoft.Maui.Controls.Xaml.dll
Controls.Foldable -> /home/vsts/work/1/s/artifacts/bin/Controls.Foldable/Debug/net10.0-android36.0/Microsoft.Maui.Controls.Foldable.dll
Microsoft.AspNetCore.Components.WebView.Maui -> /home/vsts/work/1/s/artifacts/bin/Microsoft.AspNetCore.Components.WebView.Maui/Debug/net10.0-android36.0/Microsoft.AspNetCore.Components.WebView.Maui.dll
##vso[build.updatebuildnumber]10.0.60-ci+azdo.13756416
Controls.Maps -> /home/vsts/work/1/s/artifacts/bin/Controls.Maps/Debug/net10.0-android36.0/Microsoft.Maui.Controls.Maps.dll
Controls.TestCases.HostApp -> /home/vsts/work/1/s/artifacts/bin/Controls.TestCases.HostApp/Debug/net10.0-android/Controls.TestCases.HostApp.dll
##vso[build.updatebuildnumber]10.0.60-ci+azdo.13756416
Graphics -> /home/vsts/work/1/s/artifacts/bin/Controls.TestCases.HostApp/Debug/net10.0-android/Microsoft.Maui.Graphics.dll
##vso[build.updatebuildnumber]10.0.60-ci+azdo.13756416
Essentials -> /home/vsts/work/1/s/artifacts/bin/Controls.TestCases.HostApp/Debug/net10.0-android/Microsoft.Maui.Essentials.dll
##vso[build.updatebuildnumber]10.0.60-ci+azdo.13756416
Core -> /home/vsts/work/1/s/artifacts/bin/Controls.TestCases.HostApp/Debug/net10.0-android/Microsoft.Maui.dll
Controls.BindingSourceGen -> /home/vsts/work/1/s/artifacts/bin/Controls.BindingSourceGen/Debug/netstandard2.0/Microsoft.Maui.Controls.BindingSourceGen.dll
##vso[build.updatebuildnumber]10.0.60-ci+azdo.13756416
Maps -> /home/vsts/work/1/s/artifacts/bin/Controls.TestCases.HostApp/Debug/net10.0-android/Microsoft.Maui.Maps.dll
##vso[build.updatebuildnumber]10.0.60-ci+azdo.13756416
Controls.Core -> /home/vsts/work/1/s/artifacts/bin/Controls.TestCases.HostApp/Debug/net10.0-android/Microsoft.Maui.Controls.dll
##vso[build.updatebuildnumber]10.0.60-ci+azdo.13756416
##vso[build.updatebuildnumber]10.0.60-ci+azdo.13756416
##vso[build.updatebuildnumber]10.0.60-ci+azdo.13756416
##vso[build.updatebuildnumber]10.0.60-ci+azdo.13756416
Microsoft.AspNetCore.Components.WebView.Maui -> /home/vsts/work/1/s/artifacts/bin/Controls.TestCases.HostApp/Debug/net10.0-android/Microsoft.AspNetCore.Components.WebView.Maui.dll
Controls.Foldable -> /home/vsts/work/1/s/artifacts/bin/Controls.TestCases.HostApp/Debug/net10.0-android/Microsoft.Maui.Controls.Foldable.dll
Controls.Maps -> /home/vsts/work/1/s/artifacts/bin/Controls.TestCases.HostApp/Debug/net10.0-android/Microsoft.Maui.Controls.Maps.dll
Controls.Xaml -> /home/vsts/work/1/s/artifacts/bin/Controls.TestCases.HostApp/Debug/net10.0-android/Microsoft.Maui.Controls.Xaml.dll
Build succeeded.
0 Warning(s)
0 Error(s)
Time Elapsed 00:08:10.89
Broadcasting: Intent { act=android.intent.action.CLOSE_SYSTEM_DIALOGS flg=0x400000 }
Broadcast completed: result=0
Broadcasting: Intent { act=android.intent.action.CLOSE_SYSTEM_DIALOGS flg=0x400000 }
Broadcast completed: result=0
Determining projects to restore...
Restored /home/vsts/work/1/s/src/Controls/tests/CustomAttributes/Controls.CustomAttributes.csproj (in 1.52 sec).
Restored /home/vsts/work/1/s/src/TestUtils/src/VisualTestUtils/VisualTestUtils.csproj (in 4 ms).
Restored /home/vsts/work/1/s/src/TestUtils/src/VisualTestUtils.MagickNet/VisualTestUtils.MagickNet.csproj (in 4.64 sec).
Restored /home/vsts/work/1/s/src/Controls/tests/TestCases.Android.Tests/Controls.TestCases.Android.Tests.csproj (in 6.29 sec).
Restored /home/vsts/work/1/s/src/TestUtils/src/UITest.Core/UITest.Core.csproj (in 2 ms).
Restored /home/vsts/work/1/s/src/TestUtils/src/UITest.Appium/UITest.Appium.csproj (in 2 ms).
Restored /home/vsts/work/1/s/src/TestUtils/src/UITest.NUnit/UITest.NUnit.csproj (in 444 ms).
Restored /home/vsts/work/1/s/src/TestUtils/src/UITest.Analyzers/UITest.Analyzers.csproj (in 2.45 sec).
5 of 13 projects are up-to-date for restore.
##vso[build.updatebuildnumber]10.0.60-ci+azdo.13756416
Graphics -> /home/vsts/work/1/s/artifacts/bin/Graphics/Debug/net10.0/Microsoft.Maui.Graphics.dll
Controls.CustomAttributes -> /home/vsts/work/1/s/artifacts/bin/Controls.CustomAttributes/Debug/net10.0/Controls.CustomAttributes.dll
##vso[build.updatebuildnumber]10.0.60-ci+azdo.13756416
Essentials -> /home/vsts/work/1/s/artifacts/bin/Essentials/Debug/net10.0/Microsoft.Maui.Essentials.dll
##vso[build.updatebuildnumber]10.0.60-ci+azdo.13756416
Core -> /home/vsts/work/1/s/artifacts/bin/Core/Debug/net10.0/Microsoft.Maui.dll
Controls.BindingSourceGen -> /home/vsts/work/1/s/artifacts/bin/Controls.BindingSourceGen/Debug/netstandard2.0/Microsoft.Maui.Controls.BindingSourceGen.dll
##vso[build.updatebuildnumber]10.0.60-ci+azdo.13756416
Controls.Core -> /home/vsts/work/1/s/artifacts/bin/Controls.Core/Debug/net10.0/Microsoft.Maui.Controls.dll
UITest.Core -> /home/vsts/work/1/s/artifacts/bin/UITest.Core/Debug/net10.0/UITest.Core.dll
VisualTestUtils -> /home/vsts/work/1/s/artifacts/bin/VisualTestUtils/Debug/netstandard2.0/VisualTestUtils.dll
UITest.NUnit -> /home/vsts/work/1/s/artifacts/bin/UITest.NUnit/Debug/net10.0/UITest.NUnit.dll
VisualTestUtils.MagickNet -> /home/vsts/work/1/s/artifacts/bin/VisualTestUtils.MagickNet/Debug/netstandard2.0/VisualTestUtils.MagickNet.dll
UITest.Appium -> /home/vsts/work/1/s/artifacts/bin/UITest.Appium/Debug/net10.0/UITest.Appium.dll
UITest.Analyzers -> /home/vsts/work/1/s/artifacts/bin/UITest.Analyzers/Debug/netstandard2.0/UITest.Analyzers.dll
Controls.TestCases.Android.Tests -> /home/vsts/work/1/s/artifacts/bin/Controls.TestCases.Android.Tests/Debug/net10.0/Controls.TestCases.Android.Tests.dll
Test run for /home/vsts/work/1/s/artifacts/bin/Controls.TestCases.Android.Tests/Debug/net10.0/Controls.TestCases.Android.Tests.dll (.NETCoreApp,Version=v10.0)
VSTest version 18.0.1 (x64)
Starting test execution, please wait...
A total of 1 test files matched the specified pattern.
/home/vsts/work/1/s/artifacts/bin/Controls.TestCases.Android.Tests/Debug/net10.0/Controls.TestCases.Android.Tests.dll
[xUnit.net 00:00:00.00] xUnit.net VSTest Adapter v2.8.2+699d445a1a (64-bit .NET 10.0.0)
[xUnit.net 00:00:00.12] Discovering: Controls.TestCases.Android.Tests
[xUnit.net 00:00:00.31] Discovered: Controls.TestCases.Android.Tests
NUnit Adapter 4.5.0.0: Test execution started
Running selected tests in /home/vsts/work/1/s/artifacts/bin/Controls.TestCases.Android.Tests/Debug/net10.0/Controls.TestCases.Android.Tests.dll
NUnit3TestExecutor discovered 1 of 1 NUnit test cases using Current Discovery mode, Non-Explicit run
>>>>> 04/06/2026 20:42:37 FixtureSetup for Issue34584(Android)
>>>>> 04/06/2026 20:42:40 ContentShouldNotRenderUnderStatusBarAfterNavigatingWithKeyboardOpen Start
>>>>> 04/06/2026 20:42:53 ContentShouldNotRenderUnderStatusBarAfterNavigatingWithKeyboardOpen Stop
Passed ContentShouldNotRenderUnderStatusBarAfterNavigatingWithKeyboardOpen [12 s]
NUnit Adapter 4.5.0.0: Test execution complete
Test Run Successful.
Total tests: 1
Passed: 1
Total time: 38.0801 Seconds
🟢 With fix — 🖥️ Issue34584: PASS ✅ · 514s
Determining projects to restore...
All projects are up-to-date for restore.
##vso[build.updatebuildnumber]10.0.60-ci+azdo.13756416
Graphics -> /home/vsts/work/1/s/artifacts/bin/Graphics/Debug/net10.0-android36.0/Microsoft.Maui.Graphics.dll
##vso[build.updatebuildnumber]10.0.60-ci+azdo.13756416
Essentials -> /home/vsts/work/1/s/artifacts/bin/Essentials/Debug/net10.0-android36.0/Microsoft.Maui.Essentials.dll
##vso[build.updatebuildnumber]10.0.60-ci+azdo.13756416
Core -> /home/vsts/work/1/s/artifacts/bin/Core/Debug/net10.0-android36.0/Microsoft.Maui.dll
Controls.BindingSourceGen -> /home/vsts/work/1/s/artifacts/bin/Controls.BindingSourceGen/Debug/netstandard2.0/Microsoft.Maui.Controls.BindingSourceGen.dll
##vso[build.updatebuildnumber]10.0.60-ci+azdo.13756416
Maps -> /home/vsts/work/1/s/artifacts/bin/Maps/Debug/net10.0-android36.0/Microsoft.Maui.Maps.dll
##vso[build.updatebuildnumber]10.0.60-ci+azdo.13756416
Controls.Core -> /home/vsts/work/1/s/artifacts/bin/Controls.Core/Debug/net10.0-android36.0/Microsoft.Maui.Controls.dll
##vso[build.updatebuildnumber]10.0.60-ci+azdo.13756416
##vso[build.updatebuildnumber]10.0.60-ci+azdo.13756416
##vso[build.updatebuildnumber]10.0.60-ci+azdo.13756416
Controls.Foldable -> /home/vsts/work/1/s/artifacts/bin/Controls.Foldable/Debug/net10.0-android36.0/Microsoft.Maui.Controls.Foldable.dll
Microsoft.AspNetCore.Components.WebView.Maui -> /home/vsts/work/1/s/artifacts/bin/Microsoft.AspNetCore.Components.WebView.Maui/Debug/net10.0-android36.0/Microsoft.AspNetCore.Components.WebView.Maui.dll
Controls.Xaml -> /home/vsts/work/1/s/artifacts/bin/Controls.Xaml/Debug/net10.0-android36.0/Microsoft.Maui.Controls.Xaml.dll
##vso[build.updatebuildnumber]10.0.60-ci+azdo.13756416
Controls.Maps -> /home/vsts/work/1/s/artifacts/bin/Controls.Maps/Debug/net10.0-android36.0/Microsoft.Maui.Controls.Maps.dll
Controls.TestCases.HostApp -> /home/vsts/work/1/s/artifacts/bin/Controls.TestCases.HostApp/Debug/net10.0-android/Controls.TestCases.HostApp.dll
##vso[build.updatebuildnumber]10.0.60-ci+azdo.13756416
Graphics -> /home/vsts/work/1/s/artifacts/bin/Controls.TestCases.HostApp/Debug/net10.0-android/Microsoft.Maui.Graphics.dll
##vso[build.updatebuildnumber]10.0.60-ci+azdo.13756416
Essentials -> /home/vsts/work/1/s/artifacts/bin/Controls.TestCases.HostApp/Debug/net10.0-android/Microsoft.Maui.Essentials.dll
##vso[build.updatebuildnumber]10.0.60-ci+azdo.13756416
Core -> /home/vsts/work/1/s/artifacts/bin/Controls.TestCases.HostApp/Debug/net10.0-android/Microsoft.Maui.dll
Controls.BindingSourceGen -> /home/vsts/work/1/s/artifacts/bin/Controls.BindingSourceGen/Debug/netstandard2.0/Microsoft.Maui.Controls.BindingSourceGen.dll
##vso[build.updatebuildnumber]10.0.60-ci+azdo.13756416
##vso[build.updatebuildnumber]10.0.60-ci+azdo.13756416
Maps -> /home/vsts/work/1/s/artifacts/bin/Controls.TestCases.HostApp/Debug/net10.0-android/Microsoft.Maui.Maps.dll
Controls.Core -> /home/vsts/work/1/s/artifacts/bin/Controls.TestCases.HostApp/Debug/net10.0-android/Microsoft.Maui.Controls.dll
##vso[build.updatebuildnumber]10.0.60-ci+azdo.13756416
##vso[build.updatebuildnumber]10.0.60-ci+azdo.13756416
##vso[build.updatebuildnumber]10.0.60-ci+azdo.13756416
##vso[build.updatebuildnumber]10.0.60-ci+azdo.13756416
Controls.Foldable -> /home/vsts/work/1/s/artifacts/bin/Controls.TestCases.HostApp/Debug/net10.0-android/Microsoft.Maui.Controls.Foldable.dll
Microsoft.AspNetCore.Components.WebView.Maui -> /home/vsts/work/1/s/artifacts/bin/Controls.TestCases.HostApp/Debug/net10.0-android/Microsoft.AspNetCore.Components.WebView.Maui.dll
Controls.Xaml -> /home/vsts/work/1/s/artifacts/bin/Controls.TestCases.HostApp/Debug/net10.0-android/Microsoft.Maui.Controls.Xaml.dll
Controls.Maps -> /home/vsts/work/1/s/artifacts/bin/Controls.TestCases.HostApp/Debug/net10.0-android/Microsoft.Maui.Controls.Maps.dll
Build succeeded.
0 Warning(s)
0 Error(s)
Time Elapsed 00:06:34.06
Broadcasting: Intent { act=android.intent.action.CLOSE_SYSTEM_DIALOGS flg=0x400000 }
Broadcast completed: result=0
Broadcasting: Intent { act=android.intent.action.CLOSE_SYSTEM_DIALOGS flg=0x400000 }
Broadcast completed: result=0
Determining projects to restore...
All projects are up-to-date for restore.
##vso[build.updatebuildnumber]10.0.60-ci+azdo.13756416
Graphics -> /home/vsts/work/1/s/artifacts/bin/Graphics/Debug/net10.0/Microsoft.Maui.Graphics.dll
##vso[build.updatebuildnumber]10.0.60-ci+azdo.13756416
Essentials -> /home/vsts/work/1/s/artifacts/bin/Essentials/Debug/net10.0/Microsoft.Maui.Essentials.dll
##vso[build.updatebuildnumber]10.0.60-ci+azdo.13756416
Core -> /home/vsts/work/1/s/artifacts/bin/Core/Debug/net10.0/Microsoft.Maui.dll
Controls.CustomAttributes -> /home/vsts/work/1/s/artifacts/bin/Controls.CustomAttributes/Debug/net10.0/Controls.CustomAttributes.dll
Controls.BindingSourceGen -> /home/vsts/work/1/s/artifacts/bin/Controls.BindingSourceGen/Debug/netstandard2.0/Microsoft.Maui.Controls.BindingSourceGen.dll
##vso[build.updatebuildnumber]10.0.60-ci+azdo.13756416
Controls.Core -> /home/vsts/work/1/s/artifacts/bin/Controls.Core/Debug/net10.0/Microsoft.Maui.Controls.dll
UITest.Core -> /home/vsts/work/1/s/artifacts/bin/UITest.Core/Debug/net10.0/UITest.Core.dll
VisualTestUtils -> /home/vsts/work/1/s/artifacts/bin/VisualTestUtils/Debug/netstandard2.0/VisualTestUtils.dll
UITest.NUnit -> /home/vsts/work/1/s/artifacts/bin/UITest.NUnit/Debug/net10.0/UITest.NUnit.dll
VisualTestUtils.MagickNet -> /home/vsts/work/1/s/artifacts/bin/VisualTestUtils.MagickNet/Debug/netstandard2.0/VisualTestUtils.MagickNet.dll
UITest.Appium -> /home/vsts/work/1/s/artifacts/bin/UITest.Appium/Debug/net10.0/UITest.Appium.dll
UITest.Analyzers -> /home/vsts/work/1/s/artifacts/bin/UITest.Analyzers/Debug/netstandard2.0/UITest.Analyzers.dll
Controls.TestCases.Android.Tests -> /home/vsts/work/1/s/artifacts/bin/Controls.TestCases.Android.Tests/Debug/net10.0/Controls.TestCases.Android.Tests.dll
Test run for /home/vsts/work/1/s/artifacts/bin/Controls.TestCases.Android.Tests/Debug/net10.0/Controls.TestCases.Android.Tests.dll (.NETCoreApp,Version=v10.0)
VSTest version 18.0.1 (x64)
Starting test execution, please wait...
A total of 1 test files matched the specified pattern.
/home/vsts/work/1/s/artifacts/bin/Controls.TestCases.Android.Tests/Debug/net10.0/Controls.TestCases.Android.Tests.dll
[xUnit.net 00:00:00.00] xUnit.net VSTest Adapter v2.8.2+699d445a1a (64-bit .NET 10.0.0)
[xUnit.net 00:00:00.10] Discovering: Controls.TestCases.Android.Tests
[xUnit.net 00:00:00.29] Discovered: Controls.TestCases.Android.Tests
NUnit Adapter 4.5.0.0: Test execution started
Running selected tests in /home/vsts/work/1/s/artifacts/bin/Controls.TestCases.Android.Tests/Debug/net10.0/Controls.TestCases.Android.Tests.dll
NUnit3TestExecutor discovered 1 of 1 NUnit test cases using Current Discovery mode, Non-Explicit run
>>>>> 04/06/2026 20:51:17 FixtureSetup for Issue34584(Android)
>>>>> 04/06/2026 20:51:18 ContentShouldNotRenderUnderStatusBarAfterNavigatingWithKeyboardOpen Start
>>>>> 04/06/2026 20:51:27 ContentShouldNotRenderUnderStatusBarAfterNavigatingWithKeyboardOpen Stop
Passed ContentShouldNotRenderUnderStatusBarAfterNavigatingWithKeyboardOpen [9 s]
NUnit Adapter 4.5.0.0: Test execution complete
Test Run Successful.
Total tests: 1
Passed: 1
Total time: 23.7695 Seconds
⚠️ Issues found
- ❌ Issue34584 PASSED without fix (should fail) — tests don't catch the bug
📁 Fix files reverted (2 files)
eng/pipelines/ci-copilot.ymlsrc/Controls/src/Core/Compatibility/Handlers/Shell/Android/ShellRenderer.cs
🤖 AI Summary📊 Expand Full Review —
|
| # | Source | Approach | Test Result | Files Changed | Notes |
|---|---|---|---|---|---|
| PR | PR #34621 | Call HideSoftInput() before FragmentTransaction in SwitchFragment |
❌ Gate FAILED (test doesn't detect transient) | ShellRenderer.cs + 2 test files |
Side effect: forces keyboard away before user intended |
🔧 Fix — Analysis & Comparison
Fix Candidates
| # | Source | Approach | Test Result | Files Changed | Notes |
|---|---|---|---|---|---|
| PR | PR #34621 | Call HideSoftInput() before FragmentTransaction in SwitchFragment |
❌ Gate FAILED (test doesn't catch transient) | ShellRenderer.cs + 2 test files |
Side effect: forces keyboard away before user intended |
| 1 | try-fix (claude-opus-4.6) | Post-transaction ExecutePendingTransactionsEx() + ViewCompat.RequestApplyInsets(targetView).Post() in SwitchFragment |
✅ PASS | ShellRenderer.cs + 2 test files |
No keyboard dismissal; ~2 lines of production code; test uses OnPreDrawListener to capture first-frame Y |
| 2 | try-fix (claude-sonnet-4.6) | Fix MauiWindowInsetListener.OnApplyWindowInsets — strip IME insets via Builder.SetInsets(Type.Ime(), Insets.None) during IsImeAnimating |
✅ PASS | MauiWindowInsetListener.cs + 2 test files |
Architecturally principled; fixes root cause in shared inset listener; higher blast radius |
| 3 | try-fix (gpt-5.3-codex) | Defer fragment commit via targetView.Post(...) when IME visible |
❌ FAIL | ShellRenderer.cs + 2 test files |
Timing unreliable — IME state not guaranteed stable on next frame |
| 4 | try-fix (gpt-5.4) | ViewTreeObserver.OnPreDrawListener in ShellContentFragment.OnViewCreated blocks first draw until IME insets clear |
✅ PASS | ShellContentFragment.cs + 2 test files |
Scoped to NavBarIsVisible=false pages; doesn't change inset dispatch |
| 5 | try-fix (claude-sonnet-4.6) | Temporarily set window.setSoftInputMode(SOFT_INPUT_ADJUST_NOTHING) around fragment transaction, restore via DecorView.Post() |
✅ PASS | ShellRenderer.cs + 2 test files |
Window-level fix; more lines of code; potential side effects on other navigation scenarios |
Cross-Pollination
| Model | Round | New Ideas? | Details |
|---|---|---|---|
| claude-opus-4.6 | 2 | Yes | FragmentTransaction.SetTransition(0) — remove animation to collapse race window |
| claude-sonnet-4.6 | 2 | Yes | setSoftInputMode(SOFT_INPUT_ADJUST_NOTHING) → ran as Attempt 5 |
| gpt-5.3-codex | 2 | Yes | Status-bar inset shim on destination Shell root — variant of Attempt 2 |
| gpt-5.4 | 2 | Yes | Seed ShellContentFragment with stable inset before first layout — variant of Attempt 2 |
| claude-opus-4.6 | 3 | No | Confirmed exhausted — all intervention layers covered |
| claude-sonnet-4.6 | 3 | No | Confirmed exhausted |
| gpt-5.3-codex | 3 | Yes | WindowInsetsAnimationCompat.Callback.OnEnd gate — variant of Attempt 3 (wait for IME to finish) |
| gpt-5.4 | 3 | Yes | Event-driven defer via OnEnd callback — same category as Attempt 3 |
Exhausted: Yes — Round 3 suggestions are variations of already-tested approaches (IME-wait category, already covered by PR fix and Attempt 3). Strong models (opus, sonnet) confirmed exhaustion.
Selected Fix: Attempt 1 — Post-transaction inset re-dispatch
Reason: Simplest passing fix with the smallest production footprint (~2 lines in SwitchFragment). No keyboard-dismissal side effect unlike the PR's approach. Fixes the specific trigger (missing inset re-dispatch after fragment swap with IME active) without modifying shared infrastructure (MauiWindowInsetListener, which has higher blast radius). Attempt 1's test technique (OnPreDrawListener capturing first-frame Y) is also the cleanest test improvement.
📋 Report — Final Recommendation
⚠️ Final Recommendation: REQUEST CHANGES
Phase Status
| Phase | Status | Notes |
|---|---|---|
| Pre-Flight | ✅ COMPLETE | Issue #34584, Android-only Shell/IME layout jump with NavBarIsVisible=false |
| Gate | ❌ FAILED | ANDROID — test passes both with and without fix; transient bug self-corrects before Appium can detect it |
| Try-Fix | ✅ COMPLETE | 5 attempts: 4 passing (1, 2, 4, 5), 1 failing (3); Attempt 1 selected as best |
| Report | ✅ COMPLETE |
Summary
PR #34621 addresses a real and verified Android bug: navigating to a NavBarIsVisible=false Shell page while the soft keyboard is open causes the destination content to render under the status bar before jumping into the correct position. The production fix in ShellRenderer.cs is functionally sound in concept, but the Gate ❌ FAILED because the test does not actually catch the bug — it passes in both broken and fixed states. The bug is a transient layout glitch that self-corrects before Appium's polling can observe it.
Try-Fix found 4 independently-passing alternatives, including one (Attempt 1) that is simpler and avoids the PR fix's side effect of forcibly dismissing the keyboard before every Shell navigation with an open IME.
Root Cause
During ShellRenderer.SwitchFragment, the fragment transaction is committed while the IME is still visible. The new fragment's very first layout pass receives WindowInsets that include IME insets (because MauiWindowInsetListener.IsImeAnimating is true, causing it to skip inset processing for the new view). This leaves the new fragment with paddingTop = 0, rendering content under the status bar. When the IME state later stabilizes and insets are re-dispatched, the layout corrects — producing the visible jump.
Fix Quality
Issues requiring changes:
-
Test does not catch the bug (blocking):
Assert.That(foundInvalidPosition, Is.False)passes even in the broken state because the layout self-corrects in ~50–200ms, faster than Appium's 50ms polling can reliably sample. The test must capture the first-frame render position, not poll after the fact. The proven approach (used in Attempts 1 and 4) is aViewTreeObserver.OnPreDrawListeneradded to the destination page'sTargetLabelthat records the Y position synchronously on the first draw into aFirstRenderedYlabel element. The Appium test then readsFirstRenderedYafter a short stabilization wait and asserts>= 15dp. -
Keyboard-dismissal side effect (minor):
HideSoftInput()forcibly closes the keyboard at navigation time in ALL Shell navigations where the IME is open — not just forNavBarIsVisible=falsepages. Attempt 1's approach (ExecutePendingTransactionsEx()+ViewCompat.RequestApplyInsets(targetView).Post()) avoids this side effect entirely with ~2 production lines. -
NavigateButtonunused in test:NavigateButtonis declared withAutomationId="NavigateButton"in the HostApp but never used in the UI test. Either use it (to test the button-navigation path) or remove it.
Suggested Fix (Attempt 1)
Replace HideSoftInput() in SwitchFragment with:
// In ShellRenderer.SwitchFragment, before the existing transaction code:
var rootView = _flyoutView?.AndroidView;
bool wasImeShowing = rootView != null && rootView.IsSoftInputShowing();
// ... existing transaction code (unchanged) ...
transaction.CommitAllowingStateLossEx();
if (wasImeShowing)
{
manager.ExecutePendingTransactionsEx();
targetView.Post(() =>
{
if (targetView.IsAttachedToWindow)
ViewCompat.RequestApplyInsets(targetView);
});
}And update the test to use ViewTreeObserver.OnPreDrawListener in Issue34584_DestinationPage.OnAppearing (or ContentPage constructor) to capture the first-frame Y of TargetLabel into a FirstRenderedY label, then assert FirstRenderedY >= 15 in the Appium test.
Update ContentShouldNotRenderUnderStatusBarAfterNavigatingWithKeyboardOpen to poll for transient layout issues, ensuring TargetLabel is never briefly rendered under the status bar during navigation with the keyboard open. This makes the test more robust against temporary UI glitches.
|
Thanks for the feedback! I’ve updated the test to better capture the issue by sampling the layout position over a short period after navigation, instead of relying on a single snapshot. This allows detecting transient states where the content is briefly rendered under the status bar when the keyboard is open |
Description
On Android, navigating from a page with the soft keyboard (IME) open to a page with
Shell.NavBarIsVisible="False"causes the destination page to initially render under the status bar and then jump into the correct position.This behavior is more noticeable when the destination page performs heavier UI work, and in some cases the layout may remain incorrectly positioned.
Root Cause
During
ShellRenderer.SwitchFragment, the fragment transaction is committed while the IME is still visible. Android continues to report IME-relatedWindowInsets, causing the new layout to be measured with incorrect top insets.Once the IME state stabilizes, the layout is corrected, resulting in a visible jump.
Fix
Dismiss the soft keyboard before performing the fragment transaction:
IsSoftInputShowingHideSoftInput()prior toFragmentTransactionThis ensures that
WindowInsetsare stable before the new layout is measured.Result
Testing
Added a UI test (
Issue34584) that:EntryShell.NavBarIsVisible="False"Y > 0)Note: The test validates final layout correctness, not visual animation.
Related Issues